﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using DeVierKoeden.Dynamicweb.CreateSite.DataAnonymization;

namespace DeVierKoeden.Dynamicweb.CreateSite
{
  internal class InstallSettings : ISettings, IAnonymizeSettings
  {
    /// <summary>
    /// The name of the site in IIS (which is also used as the host header for the site).
    /// </summary>
    public string SiteName { get; set; }

    /// <summary>
    /// The root folder for IIS. Can be a Dynamicweb application folder when installing a standard site, or the site's Application folder in case a custom site is set up.
    /// </summary>
    public string IisRootPath { get; set; }

    /// <summary>
    /// The path to the Admin folder that is used when the site is set up as a custom solution.
    /// </summary>
    public string IisAdminFolder { get; set; }

    /// <summary>
    /// The path to the SQL .bak file used for this site.
    /// </summary>
    public string DatabaseBackupPath { get; set; }

    public int MajorAndMinorVersion
    {
      get
      {
        try
        {
          var folder = !string.IsNullOrEmpty(IisAdminFolder) ? IisAdminFolder : IisRootPath;
          var dir = Path.GetFileName(this.DwZipSourceFile);
          var appVersion = dir.ToLower().Replace("application(", "").Replace(")", "").Replace(".zip", "");
          var els = appVersion.Split('.');
          return Convert.ToInt32(els[0] + els[1]);
        }
        catch 
        {
          return 0;
        }
      }
    }

    /// <summary>
    /// The path to the data file (with default empty data) uses for the /Files folder and database.
    /// </summary>
    public string DataFile { get; set; }

    /// <summary>
    /// The root folder of the site on disk.
    /// </summary>
    public string TargetFolder { get; set; }

    /// <summary>
    /// The /Application folder on disk when the site is set up as a custom solution.
    /// </summary>
    public string TargetApplicationFolder { get; set; }

    /// <summary>
    /// The /Files folder on disk.
    /// </summary>
    public string TargetFilesFolder { get; set; }

    /// <summary>
    /// Determines whether the sie will be based on a default empty data set, or on the Industry Solutions dataset.
    /// </summary>
    public SolutionType SolutionType { get; set; }

    /// <summary>
    /// Determines whether the site is set up as a standard or custom solution.
    /// </summary>
    public SiteType SiteType { get; set; }

    /// <summary>
    /// The location on disk where the selected Dynamicweb application will be extracted (if it doesn't exist already). 
    /// </summary>
    public string DwInstallRootFolder { get; set; }

    /// <summary>
    /// The selected Dynamicweb application (in ZIP format).
    /// </summary>
    public string DwZipSourceFile { get; set; }

    /// <summary>
    /// The instance of SQL Server used by this site.
    /// </summary>
    public string SqlServerInstance { get; set; }

    /// <summary>
    /// The name of the database in SQL Server.
    /// </summary>
    public string DatabaseName { get; set; }

    /// <summary>
    /// The path to the physical .mdf SQL Server data file used for the new database.
    /// </summary>
    public string DatabasePhysicalName { get; set; }

    /// <summary>
    /// The path to the physical .ldf SQL Server log file used for the new database.
    /// </summary>
    public string DatabaseLogName { get; set; }

    /// <summary>
    /// Determines whether or not the site's name is written to the Windows host file (and associated with 127.0.0.1).
    /// </summary>
    public bool UpdateHostsFile { get; set; }

    /// <summary>
    /// The physical pat to your Windows host file.
    /// </summary>
    public string HostsFilePath { get; set; }

    /// <summary>
    /// Whether or not to try and use (or create) an application pool called Dynamicweb 8 Sites. When set to false, a new application pool is created.
    /// </summary>
    public bool UseDefaultAppPool { get; set; }

    /// <summary>
    /// The name of the application pool under IIS used by the new site.
    /// </summary>
    public string ApplicationPoolName { get; set; }

    /// <summary>
    /// Gets the name of the Windows account associated with the application pool.
    /// </summary>
    public string ApplicationPoolAccount
    {
      get { return string.Format("IIS AppPool\\{0}", ApplicationPoolName); }
    }

    /// <summary>
    /// Determines if this site uses its own Application folder.
    /// </summary>
    public bool HasCustomApplicationFolder { get; set; }

    /// <summary>
    /// Determines if this site uses its own Files folder.
    /// </summary>
    public bool HasCustomFilesFolder { get; set; }

    /// <summary>
    /// Determines if this site uses its own SQL Server database.
    /// </summary>
    public bool HasCustomSqlDatabase { get; set; }

    /// <summary>
    /// The name of the custom SQL Server database.
    /// </summary>
    public string CustomSqlDatabase { get; set; }

    /// <summary>
    /// Determines if this site has at least one custom override (out of Application, Files and database).
    /// </summary>
    public bool HasCustomOverrides
    {
      get { return HasCustomApplicationFolder || HasCustomFilesFolder || HasCustomSqlDatabase; }
    }

    /// <summary>
    /// The physical path to a ZIP file with the custom sources.
    /// </summary>
    public string CustomZipSourceFile { get; set; }

    /// <summary>
    /// The physical path to a folder with the custom sources.
    /// </summary>
    public string CustomSourceFolder { get; set; }

    public bool ResetPassword { get; set; }
    public bool AnonymizeData { get; set; }
    public ReplacementBehavior AnonymizationMethod { get; set; }
    public string AnonymizationSuffix { get; set; }
  
    public bool MustCreateDatabase {
      get { return true; }
    }

    public bool DisableScheduledTasks { get; set; }
    public bool RandomizeUserPasswords { get; set; }
    public bool UseStandardWebConfig { get; set; }

    /// <summary>
    /// Validates the installation settings and checks the presence of the configured SQL Server instance.
    /// </summary>
    /// <returns></returns>
    internal IEnumerable<string> ValidateProperties()
    {
      if (string.IsNullOrEmpty(DwZipSourceFile))
      {
        yield return "Please specify a version of Dynamicweb to use.";
      }
      if (string.IsNullOrEmpty(SiteName))
      {
        yield return "Please specify a name for the site.";
      }

      if (HasCustomSqlDatabase && string.IsNullOrEmpty(CustomSqlDatabase))
      {
        yield return "No SQL Server backup file selected.";
      }

      if (HasCustomSqlDatabase && string.IsNullOrEmpty(CustomSqlDatabase))
      {
        yield return "No SQL Server backup file selected.";
      }

      if (UpdateHostsFile && !File.Exists(HostsFilePath))
      {
        yield return "Invalid hosts file specified. Make sure the appSetting \"HostsFile\" points to your Windows host file, or uncheck \"Update hosts file\".";
      }

      if (Directory.Exists(TargetFolder))
      {
        yield return string.Format("Target folder \"{0}\" already exists..", TargetFolder);
      }

      bool hasSqlError = false;
      using (var sqlConnection = new SqlConnection(string.Format("data source={0}; integrated security=true;", SqlServerInstance)))
      {
        try
        {
          sqlConnection.Open();
        }
        catch
        {
          hasSqlError = true;
        }
        if (hasSqlError)
        {
          yield return string.Format("The SQL server instance {0} cannot be reached. Make sure the appSetting \"SqlServerInstance\" points to a valid instance of SQL Server.", SqlServerInstance);
        }
      }
    }

    public string BuildConnectionString()
    {
      var builder = new SqlConnectionStringBuilder { DataSource = SqlServerInstance, InitialCatalog = DatabaseName, IntegratedSecurity = true};
      return builder.ToString();
    }
  }
}